package bme.andraskindler.treenventory.widget;

import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import bme.andraskindler.treenventory.activity.CameraActivity;
import bme.andraskindler.treenventory.activity.CalibrateActivity;
import bme.andraskindler.treenventory.fragment.CalibrateFragment;

/**
 * A kamerát megjelenítő View osztály, a {@link CameraActivity} használja.
 * 
 * @author andraskindler
 * 
 */
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

	public static final int RESOLUTION_SMALL = 0;
	public static final int RESOLUTION_NORMAL = 1;
	public static final int RESOLUTION_LARGE = 2;

	public static final int PICTURE_PREVIEW = 0;
	public static final int PICTURE_PROCESS = 1;

	private Camera mCamera;
	private Activity mActivity;

	public CameraSurfaceView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public CameraSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public CameraSurfaceView(Context context) {
		super(context);
	}

	@SuppressWarnings("deprecation")
	public CameraSurfaceView(final Activity activity) {
		super(activity);

		mActivity = activity;

		final SurfaceHolder surfaceHolder = this.getHolder();
		surfaceHolder.addCallback(this);
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	/**
	 * A kamera megnyitására és a paraméterek beállítására, valamint az előnézeti kép ViewHolderhez történő hozzákötésére szolgál.
	 */
	public void surfaceCreated(SurfaceHolder holder) {
		try {
			mCamera = Camera.open();
			if (mCamera != null) {
				mCamera.getParameters().setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
				mCamera.setPreviewDisplay(holder);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		if (mCamera != null) {
			mCamera.stopPreview();
			mCamera.release();
		}
	}

	/**
	 * A fotózást végző függvény, a {@link CameraActivity} és a {@link CalibrateFragment} hívja. Először beállítja a paramétereket, majd fókuszál, és elkészíti a képet.
	 * 
	 * @param flash
	 * @param size
	 * @param mode
	 */
	public void shoot(final boolean flash, final int size, final int mode) {
		final Parameters params = mCamera.getParameters();
		params.setFlashMode(flash == true ? Camera.Parameters.FLASH_MODE_AUTO : Camera.Parameters.FLASH_MODE_OFF);

		switch (size) {
		case RESOLUTION_SMALL:
			params.setPictureSize(320, 240);
			break;
		case RESOLUTION_NORMAL:
			params.setPictureSize(640, 480);
			break;
		case RESOLUTION_LARGE:
			params.setPictureSize(1280, 960);
			break;
		default:
			break;
		}

		params.setRotation(90);

		mCamera.setParameters(params);
		mCamera.autoFocus(new AutoFocusCallback() {

			public void onAutoFocus(boolean success, Camera camera) {
				mCamera.takePicture(null, null, null, new Camera.PictureCallback() {

					public void onPictureTaken(byte[] data, Camera camera) {
						final Bitmap b = (BitmapFactory.decodeByteArray(data, 0, data.length));
						if (mode == PICTURE_PROCESS) {
							((CameraActivity) mActivity).pictureTaken(b);
						} else if (mode == PICTURE_PREVIEW)
							((CalibrateActivity) mActivity).setImage(b);
					}

				});
			}
		});
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
		final Parameters params = mCamera.getParameters();
		params.set("orientation", "landscape");
		params.setRotation(90);
		mCamera.setParameters(params);
		mCamera.setDisplayOrientation(90);
		mCamera.startPreview();
	}

}